/*
 * Copyright 2008-2023 dexian.vip. All rights reserved.
 * Support: http://www.dexian.vip
 * License: http://www.dexian.vip/license
 */

package vip.dexian.admin.freemarker;

import vip.dexian.admin.freemarker.directive.PaginationDirective;
import vip.dexian.admin.freemarker.directive.PermissionDirective;
import vip.dexian.admin.freemarker.method.AbbreviateMethod;
import vip.dexian.admin.freemarker.method.CurrencyMethod;
import vip.dexian.admin.freemarker.method.MessageMethod;
import vip.dexian.core.config.oss.OssProperties;
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.SimpleDate;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.ServletContextAware;

import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

/**
 * freeMarker 配置
 *
 * @author 挺好的 2023年05月30日 15:51
 */
@Component
@Slf4j
public class FreeMarkerConfig implements ServletContextAware {

    /**
     * freemarker 配置
     */
    @Autowired
    private Configuration configuration;

    /**
     * oss配置
     */
    @Resource (name = "ossProperties")
    private OssProperties ossProperties;

    /**
     * 分页指令
     */
    @Resource (name = "paginationDirective")
    private PaginationDirective paginationDirective;

    /**
     * 权限指令
     */
    @Resource (name = "permissionDirective")
    private PermissionDirective permsDirective;

    /**
     * 国际化消息输出
     */
    @Resource (name = "messageMethod")
    private MessageMethod messageMethod;

    /**
     * 货币格式化
     */
    @Resource (name = "currencyMethod")
    private CurrencyMethod currencyMethod;

    /**
     * 字符截取
     */
    @Resource (name = "abbreviateMethod")
    private AbbreviateMethod abbreviateMethod;


    /**
     * 配置对java8 LocalDated的支持
     *
     * @param configuration
     *         配置
     */
    @Autowired
    public void configureFreemarker (Configuration configuration) {

        configuration.setObjectWrapper(new DefaultObjectWrapper(Configuration.VERSION_2_3_32) {
            @Override
            public TemplateModel wrap (Object object) throws TemplateModelException {

                if (object instanceof LocalDate localDate) {
                    return new SimpleDate(Date.valueOf(localDate));
                }

                if (object instanceof LocalTime localTime) {
                    return new SimpleDate(Time.valueOf(localTime));
                }

                if (object instanceof LocalDateTime localDateTime) {
                    return new SimpleDate(Timestamp.valueOf(localDateTime));
                }

                return super.wrap(object);
            }
        });
    }

    /**
     * 设置共享的变量
     */
    @PostConstruct
    public void setSharedVariable () {

        try {
            // 文件访问路径
            this.configuration.setSharedVariable("imageHost", this.ossProperties.getBucketHost());
            // 基础路径
            this.configuration.setSharedVariable("base", this.servletContext.getContextPath());
            // 指令
            this.configuration.setSharedVariable("pagination", this.paginationDirective);
            this.configuration.setSharedVariable("hasPermission", this.permsDirective);
            // 方法
            this.configuration.setSharedVariable("message", this.messageMethod);
            this.configuration.setSharedVariable("currency", this.currencyMethod);
            this.configuration.setSharedVariable("abbr", this.abbreviateMethod);

        } catch (TemplateModelException e) {
            log.error("设置共享变量异常", e);
        }
    }

    /**
     * servlet 上下文
     */
    private ServletContext servletContext;

    /**
     * 设置servlet 上下文
     *
     * @param servletContext
     *         servlet 上下文
     */
    @Override
    public void setServletContext (ServletContext servletContext) {
        this.servletContext = servletContext;
    }
}
